#include <glad/glad.h>
#include <imgui.h>
#include <spdlog/spdlog.h>
#include "Common.h"
#include "GlfwWindow.h"
#include "ScreenQuad.h"
#include "ShaderProgram.h"
#include "Texture2D.h"
#include "SequenceFramePlayer.h"

int main()
{
	spdlog::set_level(spdlog::level::debug);
	LOG_DEBUG("fmt", "{} + {} = {}", 2, 3, 5);
	LOG_INFO("MyTag", "{} + {} = {}", 2, 3, 5);
	LOG_WARN("MyTag", "{} + {} = {}", 2, 3, 5);
	LOG_ERROR("MyTag", "{} + {} = {}", 2, 3, 5);

	const auto pWindow  = hiveFX::CGlfwWindow::createWindow("window_config.json");
	const auto pQuad    = hiveFX::CScreenQuad::getOrCreate();
	const auto pProgram = hiveFX::CShaderProgram::createProgram("shaders/sample.vert", "shaders/sample.frag");
	const auto pTexture = hiveFX::CTexture2D::loadTexture("textures/texture.jpg");

	std::string TexPath = "textures/lightning_alpha.png";
	constexpr int   LightningSeqRows   = 4;
	constexpr int   LightningSeqCols   = 8;
	// TODO : Texture Width and Height should get from function.
	constexpr int   LightningTexWidth  = 320;
	constexpr int   LightningTexHeight = 180;
	hiveFX::CSequenceFramePlayer SeqPlayer(TexPath, LightningSeqRows, LightningSeqCols);
	if (!SeqPlayer.initTextureAndShaderProgram())
	{
		LOG_ERROR(hiveFX::tagKeyword::MAIN_TAG, "SequencePlay initialization falied.");
		return -1;
	}
	glm::vec3 Color(1.0f, 1.0f, 1.0f);

	while (!pWindow->shouldClose())
	{
		hiveFX::CGlfwWindow::pollEvents();
		hiveFX::CGlfwWindow::beginFrame();

		glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);

		if (SeqPlayer.getLoopState() || (!SeqPlayer.getLoopState() && !SeqPlayer.getFinishState()))
		{
			SeqPlayer.updateFrameAndUV(pWindow->getExtent().first, pWindow->getExtent().second);
			pQuad->bindAndDraw();
		}

		// ================ UI ================
		if (ImGui::Button("Click Me"))
		{
			LOG_INFO("Custom", "Click!");
		}
		if (ImGui::ColorEdit3("Color", &Color.x))
		{
			LOG_INFO("Custom", "Color has changed: ({},{},{})", Color.x, Color.y, Color.z);
		}
		static bool IsLoop = true;
		if (ImGui::Checkbox("Loop", &IsLoop))
		{
			SeqPlayer.setLoopPlayback(IsLoop);
		}
		static int FrameRate = 60.0f;
		if (ImGui::SliderInt("Frame Rate", &FrameRate, 1, 120))
		{
			SeqPlayer.setFramePerSecond(FrameRate);
		}
		static float Rotation = 0.0f;
		if (ImGui::SliderFloat("Rotation Angle", &Rotation, 0.0f, 360.0f))
		{
			SeqPlayer.setRotationAngle(Rotation);
		}
		static glm::vec2 ScreenUVOffset = glm::vec2(0.0f, 0.0f);
		if (ImGui::SliderFloat2("Screen UV Offset", &ScreenUVOffset[0], -1.0f, 1.0f))
		{
			SeqPlayer.setScreenUVOffset(ScreenUVOffset);
		}
		static bool IsMaintainImgAspectRatio = true;
		ImGui::Checkbox("Maintain AspectRatio", &IsMaintainImgAspectRatio);
		constexpr float ImgAspectRatio = static_cast<float>(LightningTexWidth) / static_cast<float>(LightningTexHeight);
		static glm::vec2 ScreenUVScale = glm::vec2(1.0f, 1.0f);
		if (ImGui::SliderFloat("Screen Width Scale", &ScreenUVScale[0], -1.0f, 5.0f))
		{
			if (IsMaintainImgAspectRatio) ScreenUVScale.y = ScreenUVScale.x / ImgAspectRatio;
			SeqPlayer.setScreenUVScale(ScreenUVScale);
		}
		if (ImGui::SliderFloat("Screen Height Scale", &ScreenUVScale[1], -1.0f, 5.0f))
		{
			if (IsMaintainImgAspectRatio) ScreenUVScale.x = ScreenUVScale.y * ImgAspectRatio;
			SeqPlayer.setScreenUVScale(ScreenUVScale);
		}

		hiveFX::CGlfwWindow::endFrame();
		pWindow->swapBuffers();
	}
	delete pWindow;
}